// Class describes all space objects: ships , planets ,asteroids

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using SpaceWolf.Graphics;

namespace SpaceWolf.GameLogic
{
    public class Ship :Space_Object
    {
        #region Variables
        public ShipsData data;
        private int cargoBay;
        public Laser CurrentLaser;
        public CoolantUnit Coolant=new CoolantUnit("none",0,2.5f,1);

        //private int missiles;
        //private int bravery;
        //private int exp_delta;
        //private int exp_seed;

        private bool bNeedTrack=false;
        private float distance;
        
        private int max_speed;
        private int altitude;
        public int cabtemp;

        private float speed = 0;
        private float _roll = 0;
        private float _climb = 0;
        private float _turn = 0;

        private bool docked = true;
        public float front_shield = 0;
        public float aft_shield = 0;
        public int mcount = 0;
        private float laser_temp = 0;

        private float LaserTimeToCharge = 0;
        
        private bool isAfterburnersOn=false;
        private bool isAllowDocking = false;
        private ShipOwner owner;

        public float fuel;
       
        public Space_Object trackShip;
        #endregion

        #region Properties
        public bool Docked
        {
            set
            {
                this.docked = value;
                if (docked)
                    Fefuel();
            }
            get
            {
                return this.docked;
            }
        }

       

        public bool ShowTrackCompass
        {
            get
            {
                return this.bNeedTrack;
            }
        }
        public Compass compass
        {
            get;
            set;
        }

        public Compass TrackShipCompass
        {
            get;
            set;
        }

        public float Roll
        {
            set
            {
                this._roll = value;
            }
            get
            {
                return this._roll;
            }
        }
        public float Climb
        {
            set
            {
                this._climb = value;
            }
            get
            {
                return this._climb;
            }
        }
        public float Turn
        {
            set
            {
                this._turn = value;
            }
            get
            {
                return this._turn;
            }
        }

        //public int total_cargo = 0;


        public ShipOwner Owner
        {
            get
            {
                return this.owner;
            }
        }
        
        public Laserbolt Laserbolts = new Laserbolt();

        /// <summary>
        /// Return cargo bay capacity of ship
        /// </summary>
        public int CargoBay
        {
            get
            {
                return this.cargoBay;
            }
        }

        /// <summary>
        /// Afterburners
        /// </summary>
        public bool IsAfterburnesON
        {
            set
            {
                isAfterburnersOn=value;
            }
            get
            {
                return this.isAfterburnersOn;
            }

        }
        
        public Vector3 Force
        {
            set
            {
                this.force = value;
            }
            get
            {
                return this.force;
            }
        }
        /// <summary>
        /// Distance to ship from (0,0,0)
        /// </summary>
        public float Distance
        {
            set
            {
                this.distance = value;
            }
            get
            {
                return this.distance;
            }
        }

        public int LaserTemp
        {
            get
            {
                return (int)this.laser_temp / 4;
            }
        }

        public int Speed
        {
            set
            {
                this.speed = value;
            }
            get
            {
                float speed = this.speed;
                if (this.speed > this.max_speed)
                    speed = this.max_speed;

                return Convert.ToInt32(((speed * 64) / this.max_speed) - 1);
            }
        }

        public int Fuel
        {
            get
            {
                return Convert.ToInt32(((this.fuel * 64) / data.MaxFuel) - 1);
            }
        }

        public int Altitude
        {
            set
            {
                this.altitude = value;
            }
            get
            {
                return (int)this.altitude / 4;
            }
        }

        /// <summary>
        /// 4 banks of energy
        /// </summary>
        public int[] arEnergy
        {
            get
            {
                int[] arEnergy = new int[4];
                int n = (int)data.MaxEnergy / 4;
                arEnergy[0] = (int)energy > n ? n : (int)energy;
                arEnergy[1] = (int)energy > 2 * n ? n : (int)energy - n;
                arEnergy[2] = (int)energy > 3 * n ? n : (int)energy - 2 * n;
                arEnergy[3] = (int)energy - 3 * n;

                return arEnergy;
            }
        }

        public bool AllowDocking
        {
            set
            {
                this.isAllowDocking = value;
            }
            get
            {
                return this.isAllowDocking;
            }
        }

#endregion

        public Ship(ShipsData data, ShipOwner owner, Vector3 position, Matrix Orientation, Vector3 rotations)
        {
            this.data=data;
            this.max_speed = (int)data.MaxSpeed;
            this.energy = data.MaxEnergy;
            this.cargoBay = data.CargoBayCapacity;
            //this.max_roll = 25;
            //this.max_climb=8;
            this.fuel = data.MaxFuel;
            
            this.speed = 0.5f;

            this.altitude=255;
            this.cabtemp=30;
            this.owner = owner;
            this.sName = data.Name;
            this.type = data.Type;
            this.location = position;
            this.rotations = rotations;
            this.orientation = Orientation;

            this._roll = 0;
            this._climb = 0;

            // Initializing laser system
            Laserbolts.Initialize();
        }

        private void Fefuel()
        {
            this.fuel = data.MaxFuel;
        }

        #region Handling
        public void IncreaseFlightSpeed()
        {
            if (speed < max_speed)
                speed +=0.5f;
        }

        public void IncreaseFlightSpeed(float max)
        {
            if (speed < max)
                speed += 0.5f;
        }

        public void DecreaseFlightSpeed()
        {
            if (speed > 0.5f)
                speed -= 0.5f;
        }

        public void DecreaseFlightSpeed(float min)
        {
            if (speed > min)
                speed -= 0.5f;
        }
        #endregion

        /// <summary>
        /// let's laser system work !
        /// </summary>
        public void  FireLaser()
        {
            if (laser_temp < 242)
            {
                if (LaserTimeToCharge <= 0)
                {
                    Sounds.Sound.Play("Laser");
                    LaserTimeToCharge = CurrentLaser.speed * CurrentLaser.HitPower;
                    if (CurrentLaser != Armory.LightLaser)
                        laser_temp += CurrentLaser.HitPower + LaserTimeToCharge;

                    Laserbolts.setup_and_fire(location - up - Right, direction, CurrentLaser.color,CurrentLaser.speed, false);
                    Laserbolts.setup_and_fire(location - up + Right, direction, CurrentLaser.color,CurrentLaser.speed, false);
                    //Laserbolts.setup_and_fire(location - UP + Right, direction, Microsoft.Xna.Framework.Graphics.Color.Blue,(speed/10)+0.5f, false);
                }

            }
            if (LaserTimeToCharge > 0)
            {
                LaserTimeToCharge--;// 0.5f;
            }
           
        }

        /// <summary>
        /// Laser coolant unit works
        /// </summary>
        private void CoolLaser()
        {
            if (laser_temp > 0)
            {
                float iCoolFactor=0.05f;
                if (Coolant.Name!=null)
                {
                    iCoolFactor=Coolant.UnitEffective * 0.2f;
                }
                laser_temp -= iCoolFactor;
                
            }
            //if (laser > 0)
            //{
            //    laser_temp -= .5f;
            //}
        }

        /// <summary>
        /// Shield regenerator works
        /// </summary>
        private void RegenerateShields()
        {
            if (type != ObjectTypes.Cargo)
            {
                //if (energy > 127)
                //{
                //    if (front_shield < 255)
                //    {
                //        front_shield += 0.1f;
                //        energy -= 0.01f;
                //    }

                //    if (aft_shield < 255)
                //    {
                //        aft_shield += 0.1f;
                //        energy -= 0.01f;
                //    }
                //}

                energy += 0.05f;
                //energy += cmdr.energy_unit;
                if (energy > data.MaxEnergy)
                    energy = data.MaxEnergy;
            }
        }

        public void Damage(int damage, bool front)
        {
            int shield;

            if (damage <= 0)	/* sanity check */
                return;

            isHit = true;

            shield = front ? (int)front_shield : (int)aft_shield;


            shield -= damage;
            if (shield < 0)
            {
                Energy +=shield;
                shield = 0;
            }

            if (front)
               front_shield = shield;
            else
                aft_shield = shield;
        }

        public override void Update()
        {
            if (!docked)
            {
                base.Update();   
                force *= speed;

                if (CurrentLaser != null)
                    if (Laserbolt.iBolts > 0)
                    {
                        objectState = ObjectState.Firing;
                        Laserbolts.Update(CurrentLaser.MaxDistance);
                    }
                    else
                        objectState = ObjectState.Bold;


                //Make laser cool
                CoolLaser();

                RegenerateShields();

                if (isAfterburnersOn && fuel > 0)
                {
                    fuel -= 0.03f;
                    float afterburnerSpeed = max_speed + 30;
                    IncreaseFlightSpeed(afterburnerSpeed);
                }
                else
                {
                    if (speed > max_speed)
                    {
                        DecreaseFlightSpeed(max_speed);
                    }
                }

                // Fly to Point
                if (this.State == ObjectState.Angry)
                {
                   FlyToPoint(trackShip.Location);
                }

                if (trackShip != null)
                {
                    bNeedTrack = true;
                    TrackShipCompass = UpdateCompass(trackShip.Location);
                }
                else
                {
                    bNeedTrack = false;
                }
                
            }
           
        }

        private Compass UpdateCompass(Vector3 PlanetLocation)
        {
            Vector3 dest = -PlanetLocation;
            Vector3 result = new Vector3(Vector3.Dot(dest, right),
                Vector3.Dot(dest, up),
                Vector3.Dot(dest, direction));

            result.Normalize();
            result *= 15;

            if (result.Z < 0)
            {
                return new Compass(Convert.ToInt32(result.X), Convert.ToInt32(result.Y), Microsoft.Xna.Framework.Graphics.Color.White);
            }
            else
            {
                return new Compass(Convert.ToInt32(result.X), Convert.ToInt32(result.Y), Microsoft.Xna.Framework.Graphics.Color.Red);
            }
        }

        public  void UpdatePlanetCompass(Vector3 PlanetLocation)
        {
            compass = UpdateCompass(PlanetLocation);
        }
    }
}
